#ifndef NBASEWIN_H
#define NBASEWIN_H
#define receiverName objName
#include <QMainWindow>
#include "solar/trunk/NPushButton.h"
#include "solar/trunk/NTitleBar.h"
#include "solar/trunk/NEdit.h"

class ShadoWindowQ : public QWidget{

public:
    ShadoWindowQ(QWidget *parent=nullptr) :
    QWidget(parent, Qt::FramelessWindowHint)
    {
        setGeometry(QApplication::primaryScreen()->geometry());
        setAttribute(Qt::WA_TranslucentBackground);
    }

   void paintEvent(QPaintEvent *)
   {
        QPainter captainPainter(this);
        captainPainter.setPen(Qt::NoPen);
        captainPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
        captainPainter.fillRect(captainPainter.viewport(), QColor(255,255,255,1));
   }
};


class ShadoWindow : public QWidget{

public:
    ShadoWindow(QWidget *parent=nullptr, int sdradius=8, int sdwidth=2, QColor sdcolor=QColor(89,89,89,230)) :
    QWidget(parent, Qt::FramelessWindowHint | Qt::Window)
    ,win_radius(sdradius)
    ,border_width(sdwidth)
    ,border_color(sdcolor){
        setGeometry(QApplication::primaryScreen()->geometry());
        setAttribute(Qt::WA_TranslucentBackground);
    }

    void doUpdate(const QRect &rect)
    {
        inneRect = rect;
        update();
    }

   void paintEvent(QPaintEvent *)
   {
        QPainter captainPainter(this);
        captainPainter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform);
        QPen marginPen;
        marginPen.setColor(border_color);
        marginPen.setWidth(border_width);
        captainPainter.setPen(marginPen);
        captainPainter.drawRoundedRect(inneRect, win_radius, win_radius);
    }

    QRect inneRect;

private:
    int win_radius;
    int border_width;
    QColor border_color;
};


class FloatingWindow : public QMainWindow{

    Q_OBJECT

public:
    FloatingWindow(QWidget *parent=nullptr) :
    /* 当窗口不设置 Qt::FramelessWindowHint 属性时，会导致 captureMargin 的geometry 设置报错(原生标题栏窗口最小宽限制-120)，
    并且 halfOfgeometry 函数的geometry x, y 获取，移动时，窗口异常y轴正方向位移*/
    QMainWindow(parent, QMainWindow().windowFlags() |
                        Qt::FramelessWindowHint |
                        Qt::WindowMinMaxButtonsHint)
    ,halfcut(false)
    ,dohalftime(2000)
    ,drawtype(NT::DRAWTYPE_ROUND)
    {
        setFixedSize(40,40);
        halfHideTimer.setInterval(dohalftime);
        halfHideTimer.setSingleShot(true);
        setAttribute(Qt::WA_TranslucentBackground);
        setContentsMargins(0,0,0,0);
        connect(&halfHideTimer, &QTimer::timeout, this, &FloatingWindow::halfOfgeometry);
        connect(AnimationOfhalf, &QPropertyAnimation::finished, this, [this](){winrect = geometry();});
    }

    bool captureMargin(QRect _geometry)
    {
        bool boom = false;
        int ww = _geometry.width();
        int wh = _geometry.height();
        int gx = _geometry.x();
        int gy = _geometry.y();
        int W = desktop_mask->geometry().width();
        int H = desktop_mask->geometry().height();
        if (gx < 0) {gx = 0; boom = true;}
        if (gx + ww > W) {gx = W - width(); boom = true;}
        if (gy < 0) {gy = 0; boom = true;}
        if (gy + wh > H) {gy = H - height() - taskbar_height; boom = true;}
        winrect.setRect(gx, gy, width(), height());
        setGeometry(winrect);
        return boom;
    }



    void setCurtain(QString curtain, NT::CST_BRIGHT_SPOT drawType=NT::DRAWTYPE_RECT, QColor _frameColor=QColor(151,33,207))
    {
        backPixmap = curtain;
        drawtype = drawType;
        frameColor = _frameColor;
    }

    void run(){
        halfHideTimer.start();
        update();
    }

    int taskbar_height = 0;
    QString back_pixmap;

private:
    QTimer halfHideTimer;
    QRect winrect;
    bool halfcut;
    int dohalftime;
    NT::CST_BRIGHT_SPOT drawtype=NT::DRAWTYPE_ROUND;
    QScreen *desktop_mask = QApplication::primaryScreen();
    int desktop_width = desktop_mask->geometry().width();
    int desktop_height = desktop_mask->geometry().height();
    QString backPixmap;
    QColor frameColor;
    QPropertyAnimation *AnimationOfhalf = new QPropertyAnimation(this, "geometry", this);

    void halfOfgeometry()
    {
        QRect adjustRect(0, 0, width(), height());
        int nock = 2;
        int x = winrect.x();
        int y = winrect.y();
        int w = winrect.width();
        int h = winrect.height();
        int hfw = width() / 2;
        int hfh = height() / 2;
        bool minx = -hfw - nock <= x && x <= 0;
        bool maxx = desktop_width - w - nock <= x && x <= desktop_width + hfw + nock;
        bool miny = -hfh - nock <= y && y <= nock;
        bool maxy = desktop_height - taskbar_height - h - nock <= y && y <= desktop_height + hfh + nock;
        int sminx = 0;
        int sminy = 0;
        int smaxx = desktop_width - w;
        int smaxy = desktop_height - taskbar_height - h;
        int hminx = -hfw;
        int hminy = -hfh;
        int hmaxx = desktop_width - hfw;
        int hmaxy = desktop_height - taskbar_height - hfh;
        if (halfcut) // half hide
        {
            if (minx)
            {
                adjustRect.setX(0);
                if (miny) adjustRect.setY(sminy);
                else if (maxy) adjustRect.setY(smaxy);
                else adjustRect.setY(geometry().y());
            }
            if (miny)
            {
                adjustRect.setY(0);
                if (minx) adjustRect.setX(sminx);
                else if (maxx) adjustRect.setX(smaxx);
                else adjustRect.setX(geometry().x());
            }
            if (maxx)
            {
                adjustRect.setX(smaxx);
                if (miny) adjustRect.setY(sminy);
                else if (maxy) adjustRect.setY(smaxy);
                else adjustRect.setY(geometry().y());
            }
            if (maxy)
            {
                adjustRect.setY(smaxy);
                if (minx) adjustRect.setX(sminx);
                else if (maxx) adjustRect.setX(smaxx);
                else adjustRect.setX(geometry().x());
            }
        }
        else // show
        {
            if (minx)
            {
                adjustRect.setX(- hfw);
                if (miny) adjustRect.setY(hminy);
                else if (maxy) adjustRect.setY(hmaxy);
                else adjustRect.setY(geometry().y());
            }
            if (miny)
            {
                adjustRect.setY(- hfh);
                if (minx) adjustRect.setX(hminx);
                else if (maxx) adjustRect.setX(hmaxx);
                else adjustRect.setX(geometry().x());
            }
            if (maxx)
            {
                adjustRect.setX(hmaxx);
                if (miny) adjustRect.setY(hminy);
                else if (maxy) adjustRect.setY(hmaxy);
                else adjustRect.setY(geometry().y());
            }
            if (maxy)
            {
                adjustRect.setY(hmaxy);
                if (minx) adjustRect.setX(hminx);
                else if (maxx) adjustRect.setX(hmaxx);
                else adjustRect.setX(geometry().x());
            }
        }
        AnimationOfhalf->setStartValue(geometry());
        AnimationOfhalf->setEndValue(adjustRect);
        AnimationOfhalf->setDuration(200);
        AnimationOfhalf->start();
    }

    void enterEvent(QEvent *){
        halfcut = true;
        winrect = geometry();
        AnimationOfhalf->stop();
        halfOfgeometry();
    }

    void leaveEvent(QEvent *){
        halfcut = true;
        halfcut = false;
        winrect = geometry();
        AnimationOfhalf->stop();
        halfOfgeometry();

    }

    void mouseReleaseEvent(QMouseEvent *){
        emit msev_rls();
    }

    void paintEvent(QPaintEvent *)
   {
        QPainter captainPainter(this);
        captainPainter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform);
        QRect view_rect = captainPainter.window();
        QPainterPath path;
        if (frameColor.isValid())
        {
            QPen pen;
            pen.setColor(frameColor);
            captainPainter.setPen(pen);
        }
        else
        {
            captainPainter.setPen(Qt::NoPen);
        }
        QPixmap bkpix(backPixmap);
        if (bkpix.isNull())
        {
            captainPainter.setBrush(QColor("white"));
        }
        else
        {
            bkpix.setDevicePixelRatio(bkpix.height() / height());
            captainPainter.setBrush(bkpix);
        }
        if (drawtype == NT::DRAWTYPE_ROUND)
        {
            path.addRoundedRect(view_rect, width() / 2, height() / 2);
        }
        else
        {
            path.addRect(view_rect);
        }
        captainPainter.drawPath(path);
    }

signals:
    void msev_rls();
};


class NMainWindow : public QMainWindow{

    Q_OBJECT

public:
    NMainWindow(QWidget *parent=nullptr);

    ~NMainWindow();

    void d_margin_radius(QMargins margin=QMargins(9, 4, 9, 4), int radius=4);

    void d_filler_color(QList<QColor> color);

    void d_filler_color(QColor color);

    void d_filler_color(QString color);

    void d_filler_pixmap(QString curtain);

    void d_floating_pixmap(QString curtain);

    void d_filler_orientation(NT::CST_BRIGHT_SPOT orien);

    void d_filler_enable(NTitleBar::FillerType Type, bool Enable);

    void d_filler_clear(NTitleBar::FillerType Type);

    void d_cursor(QCursor cursor);

    void setVisible(bool visible) override;

    void close();

    NTitleBar* captionBar();

    void move(int ax, int ay);
    void move(QPoint point);
    void resize(int w, int h);
    void resize(const QSize &);
    void setFixedHeight(int h);
    void setFixedSize(int w, int h);
    void setMaximumHeight(int maxh);
    void setMinimumHeight(int minh);
    void setMaximumSize(int maxw, int maxh);
    void setMaximumSize(const QSize &s);
    void setMinimumSize(int minw, int minh);
    void setMinimumSize(const QSize &s);

protected:
    QMargins win_margin;
    int win_radius;
    int taskbar_height;
    MOUSE_ATTRIBUTE MSEVKEY;

    void d_painter_effectrange(QRect _range, QList<QColor> _flrcolor={QColor(Qt::transparent)});

    void paintEvent(QPaintEvent *Event) override;

    bool eventFilter(QObject *watched, QEvent *Event) override;

    void notify(NTitleBar::ButtomType buttomType, QPoint event_pos=QPoint(0,0));

    void winmvAndstretchOff(bool enable=false);

private:
    QByteArray uniqueKey;
    QScreen *desktop_mask = QApplication::primaryScreen();
    NT::LOCALTION margin_touch_type;
    QPoint ms_start;
    QPoint ms_move;
    QCursor move_cursor;
    int rvs_scount;
    int rvs_hcount;
    int rvs_sinteval;
    int rvs_hinteval;
    int exp_sinteval;
    int win_cornered;
    int linear_backtime;
    QRect init_win_rect; // 窗口可见时的位置
    QRect wmax_ago_rect; // 最大化之前的位置
    QRect near_win_rect; //最近的位置
    QRect alte_win_rect;
    QRect effect_range;
    QPixmap back_pixmap;
    QMap<QString, QList<QColor>> back_color_map;
    QSize accept_minsize;
    QSize accept_capminsize;
    NT::CST_BRIGHT_SPOT linear_orien;
    QTimer blurTimer;
    QTimer stretchTimer;

    QMap<QString, bool> _switch;
    QMap<NTitleBar::FillerType,  bool> RdoMap_FillerType;
    NTitleBar *TT_Object = new NTitleBar(this);
    FloatingWindow *View_hoverMask = new FloatingWindow(this);
    ShadoWindow *View_shadowMask = new ShadoWindow(this, win_radius, 2);
    QParallelAnimationGroup *backAnimationGroup = new QParallelAnimationGroup();
    QPropertyAnimation *Animainback = new QPropertyAnimation(this, "geometry", this);
    QPropertyAnimation *Animacpback = new QPropertyAnimation(TT_Object, "geometry", this);

    void window_change_stretch();

    void window_change_start(QPoint mvp);

    void window_change_end();

    void window_change_centra();

    void d_caption_press(NTitleBar::BasicButtom buttom);

    void window_change_stretch(QPoint mvp);

    void window_change_stretchq(int x, int y, int w, int h);

    void window_change_catchup();

    void caption_batcatch_up();

    void hover_release_event();

    void opacityTimer();

    void animation_running_end();

    void eventFilterT(QPoint _pos);

    NT::LOCALTION marginsTouch(QPoint _pos, int radius, int pardonValue=2);

signals:
    void bsic_quit(); //程序退出信号
    void bsic_posmv(); // 窗口移动信号
    void bsic_nrrls();
    void bsic_icopre(); //标题图标点击信号
    void bsic_ttlepre(); //标题文字点击信号
};


class MessageBoxQ : public NMainWindow{

    Q_OBJECT

public:

    MessageBoxQ(QWidget *_this_,
                QList<QString> options = {"sure", "skip"},
                int MessageBoxQType = Type::MSG_Info,
                QString scdr_mesage = NULL,
                QString main_mesage = NULL,
                QVariant content_backcolor = QColor(240,243,246),
                QVariant caption_backcolor = QColor(240,243,246));

    ~MessageBoxQ();

    enum Type{
        MSG_Error,
        MSG_Warning,
        MSG_Dedly,
        MSG_Info,
        MSG_Question
    };

    void setOptions(QList<QString> selection);

    void mouseCheckEvent(QString objectName);

private:
    QWidget *global_pwidget = new QWidget();
    QVBoxLayout *main_vbox = new QVBoxLayout(global_pwidget);
    QVBoxLayout *bottom_vbox = new QVBoxLayout();
    QLabel *message_text = new QLabel(global_pwidget);
    ShadoWindowQ *shadoMask = new ShadoWindowQ();
    QMap<int, QHBoxLayout*> layoutmap;

    int iotionsNum;
    int _prt_x;
    int _prt_y;
    int _prt_w;
    int _prt_h;
    QTimer delayShowTimer;
    Extend definfc;
    QFont globalFont = QFont("KaiTi_GB2312", 15);

    void addpushbuttom(int &_row, int &_addtion, QPushButton *_buttom=nullptr);

    template<typename doiwidget>
    void backparser(doiwidget *receive, QVariant back){
        if (back.metaType().id() == QMetaType::QString && back.isValid())
        {
            receive->d_filler_enable(NTitleBar::BACKPIXMAP, true);
            receive->d_filler_pixmap(back.toString());
        }
        else if (back.metaType().id() == QMetaType::QColor && back.isValid())
        {
            QColor i = back.value<QColor>();
            receive->d_filler_enable(NTitleBar::BACKCOLOR, true);
            receive->d_filler_color(i);
        }
    }

signals:
    void checkEvent(QPushButton *);
};


class WaitaMinit : public QLabel{

public:

    WaitaMinit(QString _moviefile=NULL, QWidget *parent=nullptr) : QLabel(parent){
        movie->setFileName(_moviefile);
        setMovie(movie);
        setParent(parent);
        setWindowFlag(Qt::FramelessWindowHint);
        setAttribute(Qt::WA_TranslucentBackground);
        setAlignment(Qt::AlignCenter);
    }

    enum type{
        start,
        pause,
        reset
    };

    ~WaitaMinit(){
        delete movie;
    }

    void d_file(QString _moviefile)
    {
        movie->setFileName(_moviefile);
    }

    void d_config(WaitaMinit::type type){
        switch (type)
        {
            case start:
                if (movie->state() == QMovie::NotRunning)
                {
                    movie->start();
                }
                else
                {
                    movie->setPaused(true);
                }
                break;
            case reset:
                movie->start();
                break;
            case pause:
                movie->setPaused(false);
                break;
        }
    }

    void d_centra(QRect rect){
        rectarg = rect;
        setVisible(true);
    }

    void setVisible(bool visible){
        int x = rectarg.x();
        int y = rectarg.y();
        int w = rectarg.width();
        int h = rectarg.height();
        QLabel::setVisible(visible);
        x += abs(w - width()) / 2;
        y += abs(h - height()) / 2;
        move(x, y);
        setMinimumSize(60, 60);
        movie->resized(size());
    }

private:
    QRect rectarg;
    QMovie *movie = new QMovie();
};


#endif // NBASEWIN_H
